﻿using System;
using System.Collections.Generic;
using System.Linq;
using Wicture.DbRESTFul;
using Wicture.EPC.OnlineQueryProxy.Agents;

namespace Wicture.EPC.OnlineQueryProxy
{
    public static class SchedulerManager
    {
        private static List<IScheduler> schedulers = new List<IScheduler>
        {
            new RandomStrategyScheduler(),
            new WeightedRoundRobinStrategyScheduler(),
        };

        private static IScheduler currentScheduler;

        static SchedulerManager()
        {
            var strategy = ConfigurationManager.Settings.Variables["SchedulerStrategy"];
            SetStrategy(strategy);
        }

        public static void SetStrategy(string strategy)
        {
            if (!string.IsNullOrEmpty(strategy))
            {
                currentScheduler = schedulers.FirstOrDefault(s => s.Strategy == strategy);
            }
        }

        public static void UpdateWeightRange(List<Agent> agents, string processorName)
        {
            if (currentScheduler.Strategy == "WeightedRoundRobin")
            {
                UpdateWeightRangeInternal(agents, processorName);
            }
        }

        private static void UpdateWeightRangeInternal(List<Agent> agents, string processorName)
        {
            var agts = agents.Where(a => a.IsReady && a.IsOnline && a.Enabled && a.ProcessorName == processorName);
            var total = agts.Sum(s => s.Weight);
            var counter = 0;

            foreach (var agent in agts)
            {
                agent.WeightRange.Start = 1m * counter / total;
                counter += agent.Weight;
                agent.WeightRange.End = 1m * counter / total;
            }
        }

        public static Agent GetNext(List<Agent> agents, string processorName)
        {
            var agts = agents.Where(a => a.IsReady && a.IsOnline && a.Enabled && a.ProcessorName == processorName).ToList();
            if (agts.Count < 1) throw new Exception("没有可用代理服务器。");

            if (agts.All(a => a.IsBusy)) throw new Exception($"服务器繁忙，请稍后再试。");

            return currentScheduler.GetNext(agts);
        }
    }
}
